#pragma once

#include <iostream>
/// using namespace std;
#include <string>
#include <unordered_map>
#include <sys/epoll.h>
#include <unistd.h>

#define SIZE 128
#define NUM 64
class Event;
typedef int (*callback_t)(Event *ev);
class Reactor;

// 每一个socket对应一个Event
class Event
{
public:
    int _sock;

    // 接受缓冲区
    std::string inbuffer;
    // 发送缓冲区
    std::string outbuffer;
    // sock回调函数
    callback_t _recver;
    callback_t _sender;
    callback_t _errorer;
    // 回指reactor的指针
    Reactor *R;

public:
    Event(int sock = -1)
    {
        _sock = sock;
        _recver = nullptr;
        _sender = nullptr;
        _errorer = nullptr;
        R = nullptr;
    }

    void CallbackRegister(callback_t recver, callback_t sender, callback_t errorer)
    {
        _recver = recver;
        _sender = sender;
        _errorer = errorer;
        std::cout << "回调方法注册成功！" << std::endl;
    }

    ~Event()
    {
    }
};

// 反应堆
class Reactor
{
public:
    Reactor()
    {
        _epfd = -1;
    }

    void Initializer()
    {
        _epfd = epoll_create(SIZE);
        if (_epfd < 0)
        {
            std::cerr << "epoll_create error" << std::endl;
            exit(2);
        }
        std::cout << "InitReactor success" << std::endl;
    }

    // 将事件托管给反应堆
    bool InsertEvent(Event *evp, uint32_t event)
    {

        // 注册进反应堆
        epoll_event _ev;
        _ev.data.fd = evp->_sock;
        _ev.events = event;
        if (epoll_ctl(_epfd, EPOLL_CTL_ADD, evp->_sock, &_ev) < 0)
        {
            std::cerr << "epoll_ctl error,fd:" << evp->_sock << std::endl;
            return false;
        }
        // 插入map
        _events.insert({evp->_sock, evp});
        std::cout << "fd:" << evp->_sock << ":事件托管给反应堆" << std::endl;
        return true;
    }
    // 删除已连接关闭的事件
    void EraseEvent(Event *evp)
    {
        int sock = evp->_sock;
        auto it = _events.find(sock);
        if (it != _events.end())
        {
            // 1.从反应堆移出
            epoll_ctl(_epfd, EPOLL_CTL_DEL, sock, nullptr);
            // 2.从map中删除
            _events.erase(sock);
            std::cout << "已将fd:" << sock << "移出反应堆" << std::endl;
            // 3.关闭文件描述符
            close(sock);
            // 4.释放事件资源
            delete evp;
            std::cout << "释放资源成功" << std::endl;
        }
    }

    // 判断sock是否还存在map
    bool IsSockOk(int sock)
    {
        auto it = _events.find(sock);
        return it != _events.end();
    }

    // 
    int EnableRW(int sock,bool EnbRead,bool EnbWrite)
    {
        epoll_event ev;
        ev.events = EPOLLET | (EnbRead?EPOLLIN:0) | (EnbWrite?EPOLLOUT:0);
        ev.data.fd = sock;
        if(epoll_ctl(_epfd,EPOLL_CTL_MOD,sock,&ev) < 0)
        {
            std::cerr << "epoll_ctl error" << std::endl;
            return -1;
        }
        return 0;
    }

    // 事件派发器
    void Dispatcher(int timeout)
    {
        epoll_event revs[NUM];
        int n = epoll_wait(_epfd, revs, NUM, timeout);
        for (int i = 0; i < n; ++i)
        {
            int sock = revs[i].data.fd;
            if (revs[i].events & EPOLLERR || revs[i].events & EPOLLHUP)
                revs[i].events |= EPOLLIN | EPOLLOUT;
            if (revs[i].events & EPOLLIN)
            {
                // 读取数据就绪,调用接受回调函数
                if (IsSockOk(sock) && _events[sock]->_recver) // 判断sock还有效才能进行操作
                    _events[sock]->_recver(_events[sock]);
            }
            if (revs[i].events & EPOLLOUT)
            {
                // 可写，调用发送函数
                if (IsSockOk(sock) && _events[sock]->_sender)
                    _events[sock]->_sender(_events[sock]);
            }
        }
    }

    ~Reactor()
    {
    }

private:
    int _epfd;
    std::unordered_map<int, Event *> _events;
};